﻿using System.Collections.Generic;
using System.Reflection;
using NLite.Reflection;
using NLite.Collections;

namespace NLite.Internal
{
    class DynamicMethodFactoryProxy:IDynamicMethodFactory
    {
        private IDynamicMethodFactory RealFactory = new DynamicMethodFactory();

        private IMap<MethodInfo, Proc> actionCache = new ConcurrentMap<MethodInfo, Proc>();
        private IMap<MethodInfo, Func> funcCache = new ConcurrentMap<MethodInfo, Func>();
        private IMap<ConstructorInfo, ConstructorHandler> factoryMethodCache = new ConcurrentMap<ConstructorInfo, ConstructorHandler>();
        private IMap<MemberInfo, Getter> getterCache = new ConcurrentMap<MemberInfo, Getter>();
        private IMap<MemberInfo, Setter> setterCache = new ConcurrentMap<MemberInfo, Setter>();

        private DynamicMethodFactoryProxy() { }

        public static readonly DynamicMethodFactoryProxy Instance = new DynamicMethodFactoryProxy();

        public Proc CreateProcMethod(System.Reflection.MethodInfo method)
        {
            return actionCache.GetOrAdd(method, () => RealFactory.CreateProcMethod(method));
        }

        public Func CreateFuncMethod(System.Reflection.MethodInfo method)
        {
            return funcCache.GetOrAdd(method, () => RealFactory.CreateFuncMethod(method));
        }

        public ConstructorHandler CreateConstructorMethod(System.Reflection.ConstructorInfo constructor)
        {
            return factoryMethodCache.GetOrAdd(constructor, () => RealFactory.CreateConstructorMethod(constructor));
        }
       
        public Getter CreateGetter(System.Reflection.MemberInfo member)
        {
            return getterCache.GetOrAdd(member, () => RealFactory.CreateGetter(member));
        }

        public Setter CreateSetter(System.Reflection.MemberInfo member)
        {
            return setterCache.GetOrAdd(member, () => RealFactory.CreateSetter(member));
        }
    }
}
